package org.andao.commons.service.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.andao.commons.model.Message;
import org.andao.commons.model.MessageReceiver;
import org.andao.commons.model.MessageSender;
import org.andao.commons.model.MessageStat;
import org.andao.commons.service.AttachsService;
import org.andao.commons.service.SysMsgService;
import org.andao.commons.taglib.function.JstlCustomFunction;
import org.andao.core.base.service.BaseServiceImpl;
import org.andao.core.dao.helper.Page;
import org.andao.core.exception.ServiceException;
import org.andao.core.utils.ExDateUtils;
import org.andao.core.utils.ExStringUtils;
import org.andao.security.model.OrgUnit;
import org.andao.security.model.Role;
import org.andao.security.model.User;
import org.andao.security.service.OrgUnitService;
import org.andao.security.service.RoleService;
import org.andao.security.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * 系统消息与通知服务.
 * @author Marco.hu(hzg139@163.com)
 *
 */
@Transactional
@Service("sysMsgService")
public class SysMsgServiceImpl extends BaseServiceImpl<Message> implements SysMsgService {

	@Autowired
	@Qualifier("attachsService")
	private AttachsService attachsService;
	
	@Autowired
	@Qualifier("orgUnitService")
	private OrgUnitService orgUnitService;//注入组织服务
	
	@Autowired
	@Qualifier("roleService")
	private RoleService roleService;//注入角色服务
	
	@Autowired
	@Qualifier("userService")
	private UserService userService;//注入用户服务
	
	//保存消息
	@Override
	public void saveMessage(MessageSender messageSender, MessageReceiver messageReceiver, String[] attachIds) throws ServiceException {
		Message message = messageSender.getMessage();
		//保存消息
		save(message);
		//保存发送者
		exGeneralHibernateDao.save(messageSender);	
		//保存附件
		attachsService.updateAttachByFormId(attachIds, message.getResourceid(), Message.class.getSimpleName(), messageSender.getSenderId(), messageSender.getSender());
		//保存接受者	
		exGeneralHibernateDao.save(messageReceiver);				
		 
	}
	
	//更新消息
	@Override
	public void updateMessage(MessageSender messageSender, MessageReceiver messageReceiver, String[] attachIds) throws ServiceException {
		Message message = messageSender.getMessage();
		exGeneralHibernateDao.update(messageSender);
		attachsService.updateAttachByFormId(attachIds, message.getResourceid(), Message.class.getSimpleName(), messageSender.getSenderId(), messageSender.getSender());
		exGeneralHibernateDao.saveOrUpdate(messageReceiver);			
	}
	
	//删除消息
	@Override
	public void deleteMessage(String type, String[] ids) throws ServiceException {
		if(type.equalsIgnoreCase("inbox")){//收件箱	
			if(ids!=null && ids.length>0){
				for (String id : ids) {					
					MessageReceiver messageReceiver = (MessageReceiver)exGeneralHibernateDao.findUniqueByProperty(MessageReceiver.class, "message.resourceid", id);
					exGeneralHibernateDao.delete(messageReceiver);						
				}
			}
		} else if(type.equalsIgnoreCase("draftbox")||type.equalsIgnoreCase("sendbox")){//草稿箱或发件箱
			if(ids!=null && ids.length>0){
				for (String id : ids) {
					MessageSender messageSender = (MessageSender)exGeneralHibernateDao.findUniqueByProperty(MessageSender.class, "message.resourceid", id);	
					exGeneralHibernateDao.delete(messageSender);	
				}
			}
		} 
	}	
	
	//未读消息数
	@Override
	@Transactional(readOnly=true)
	public Integer unreadMessageCount(User user) throws ServiceException {
		StringBuilder hql  = new StringBuilder();
		
		hql.append("select count(r) from "+MessageReceiver.class.getSimpleName()+" r where r.isDeleted = 0  and r.message.sendTime <= current_date() ");
		//查找自己的
		hql.append(" and ( 1=0 or r.receiveType = 'user' and r.userIds like '%"+user.getResourceid()+"%' ");
		//查找本组织的
		if(user.getOrgUnit()!=null)
			hql.append(" or r.receiveType = 'org' and r.orgUnitCodes like '%"+user.getOrgUnit().getUnitCode()+"%' ");
		hql.append( " or r.receiveType = 'role' and (1=0 ");
		//查找本角色的
		for (Role r : user.getRoles()) 
			hql.append(" or r.roleCodes like '%"+r.getRoleCode()+"%' ");
		hql.append( " ))");
		hql.append(" and r.message.resourceid not in (select s.message.resourceid from MessageStat s where s.isDeleted=0 and s.receiverId='"+user.getResourceid()+"' ) ");
		Long count = exGeneralHibernateDao.findUnique(hql.toString());
		
		return count == null ? 0 : count.intValue();
	}
	
	/**
	 *  发送消息
	 * @param sendUserId        消息发送者用户ID
	 * @param sendUserCnName    消息发送者用户中文名
	 * @param sendUsersOrgUnit  消息发送者所属的组织单位
	 * @param msgType   		消息类型
	 * @param title     		消息标题
	 * @param msg       		消息内容
	 * @param receiverUserId  消息接收者
	 * @param receiveType       消息的接收类型:按用户、组织...
	 * @param formId  			消息发送者所属的formId
	 * @param formType  		消息发送者所属的formType
	 */
	public void sendMsg(String sendUserId,String sendUserCnName,OrgUnit sendUsersOrgUnit,String msgType,String title,
						String msg,String receiverUserId,String receiveType,String formId,String formType){

		Message message 				= new Message();
		MessageSender messageSender 	= new MessageSender();
		MessageReceiver messageReceiver = new MessageReceiver();
		
		message.setContent(msg);
		message.setMsgTitle(title);
		message.setMsgType(msgType);
		message.setSendTime(ExDateUtils.getCurrentDateTime());
		message.setFormId(formId);
		message.setFormType(formType);
		
		messageSender.setMessage(message);
		messageSender.setOrgUnit(sendUsersOrgUnit);
		messageSender.setSender(sendUserCnName);
		messageSender.setSenderId(sendUserId);

		messageReceiver.setMessage(message);
		messageReceiver.setReceiveType(receiveType);
		messageReceiver.setUserIds(receiverUserId);
		
		save(message);
		exGeneralHibernateDao.save(messageSender);		
		exGeneralHibernateDao.save(messageReceiver);	
	}
	
	/**
	 * 发送消息 
	 * @param receivers     接收者     : 按组织(组织编码)/按角色(角色编码)/按用户(用户名)
	 * @param receiveType   接收类型     按组织/ 按角色/按用户
	 * @param sendUser      发送者
	 * @param msgTitle      消息标题
	 * @param msgContent    消息 key是接收者，value是消息内容
	 * @param msgType       消息类型:  tips - 温馨提示 / sysmsg - 系统消息/ usermsg - 用户消息
	 * @param isdraft       是否草稿  Y/N
	 * @param isReply       消息是否允许回复  Y/N
	 * @param formType      表单类型
	 * @param formId        表单ID
	 * @throws ServiceException
	 */
	@Override
	public void sendMsgByIds(List<String> receivers,String receiveType,User sendUser,Map<String, String> msgTitle,Map<String, String> msgContent,String msgType,String isdraft ,String isReply,String formType,String formId)throws ServiceException {
		/*
		Date curTime                 = new Date();
		List<Object[]> msgParam      = new ArrayList<Object[]>();
		List<Object[]> senderParam   = new ArrayList<Object[]>();
		List<Object[]> receiverParam = new ArrayList<Object[]>();
		
		String msgSql      			 = "insert into edu_portal_msg (resourceid,msgtitle,msgtype,content,sendtime,isdraft,isreply,formid,formtype,version,isdeleted) values (?,?,?,?,?,?,?,?,?,?,?)";
		String senderSql   			 = "insert into edu_portal_sender (resourceid,msgid,senderid,sender,orgunitid,version,isdeleted) values (?,?,?,?,?,?,?)";
		String receiverSql			 = "";
		if (Constants.msgReceiveType.org.toString().equals(receiveType)) {
			receiverSql              = "insert into edu_portal_receiver (resourceid,receivetype,msgid,orgunitcodes,version,isdeleted) values (?,?,?,?,?,?)";  
		}else if (Constants.msgReceiveType.role.toString().equals(receiveType)) {
			receiverSql              = "insert into edu_portal_receiver (resourceid,receivetype,msgid,rolecodes,version,isdeleted) values (?,?,?,?,?,?)";  
		}else if (Constants.msgReceiveType.user.toString().equals(receiveType)) {
			receiverSql              = "insert into edu_portal_receiver (resourceid,receivetype,msgid,usernames,version,isdeleted) values (?,?,?,?,?,?)";  
		}else {
			throw new ServiceException("请传入正确的消息接收者类型！");
		}
		
		GUIDUtils.init();
		for (String receive:receivers) {
			String msgid 			 = GUIDUtils.buildMd5GUID(false);
			//消息id,消息标题,消息类型,消息内容,发送时间,是否草稿,是否可回复,版本,是否删除				
			msgParam.add(new Object[]{msgid,msgTitle.get(receive),msgType,msgContent.get(receive),curTime,ExStringUtils.trimToEmpty(isdraft),ExStringUtils.trimToEmpty(isReply),ExStringUtils.trimToEmpty(formId),ExStringUtils.trimToEmpty(formType),0L,0});
			//发送id,消息id,发送人id,发送人姓名,发送人组织单位,版本,是否删除
			senderParam.add(new Object[]{GUIDUtils.buildMd5GUID(false),msgid,sendUser.getResourceid(),sendUser.getCnName(),sendUser.getOrgUnit().getResourceid(),0L,0});
			//接收id,接收类型,消息id,接受者登录名,版本,是否删除
			receiverParam.add(new Object[]{GUIDUtils.buildMd5GUID(false),receiveType,msgid,receive,0L,0});
		}
		
		baseSupportJdbcDao.getBaseJdbcTemplate().getJdbcTemplate().batchUpdate(msgSql, msgParam);
		baseSupportJdbcDao.getBaseJdbcTemplate().getJdbcTemplate().batchUpdate(senderSql,senderParam);
		baseSupportJdbcDao.getBaseJdbcTemplate().getJdbcTemplate().batchUpdate(receiverSql, receiverParam);
		
		logger.info("消息发送成功,共{}条,{}",new Object[]{receivers.size(),curTime});
		*/
	}
	
	//查询该消息是否已读
	@Override
	@Transactional(readOnly=true)
	public boolean isMessageReaded(String msgId, String readUserId)	throws ServiceException {
		Long stat = exGeneralHibernateDao.findUnique("select count(s) from "+MessageStat.class.getSimpleName()+
					" s where s.isDeleted=? and s.message.resourceid=? and s.receiverId =?", new Object[]{0,msgId,readUserId});
		return (stat!=null&&stat.intValue()>0)?true:false;
	}

	//获取用户已读消息ID集	
	@Override
	@SuppressWarnings("unchecked")
	@Transactional(readOnly=true)
	public List<String> getIsReadMsgIds(String userId) throws ServiceException {
		return (List<String>)exGeneralHibernateDao.findByHql("select message.resourceid from "+MessageStat.class.getSimpleName()+
					" where isDeleted=? and receiverId = ? order by message.sendTime desc ", 0,userId);
	}

	//根据条件查找发送消息列表
	@Override
	@Transactional(readOnly=true)
	public Page findSendedMessageByCondition(Map<String, Object> condition,	Page objPage) throws ServiceException {
		Map<String,Object> values =  new HashMap<String, Object>();
		StringBuilder hql = new StringBuilder();
		
		hql.append(" from "+MessageSender.class.getSimpleName()+" where isDeleted = :isDeleted ");		
		values.put("isDeleted", 0);
				
		if(condition.containsKey("msgTitle")){//标题
			hql.append(" and lower(message.msgTitle) like lower(:msgTitle) ");
			values.put("msgTitle", "%"+condition.get("msgTitle")+"%");
		}	
		if(condition.containsKey("msgType")){//类型
			hql.append(" and message.msgType =:msgType ");
			values.put("msgType", condition.get("msgType"));
		}	
		if(condition.containsKey("isDraft")){//是否草稿
			hql.append(" and message.isDraft =:isDraft ");
			values.put("isDraft", condition.get("isDraft"));
		}
		if(condition.containsKey("senderId")){//发送人
			hql.append(" and senderId =:senderId ");
			values.put("senderId", condition.get("senderId"));
		}		
		if(condition.containsKey("startDate")){//开始时间
			hql.append(" and message.sendTime >= to_date('"+condition.get("startDate").toString()+"','yyyy-MM-dd') ");
		}
		if(condition.containsKey("endDate")){//结束时间
			hql.append( " and message.sendTime <= to_date('"+condition.get("endDate").toString()+"','yyyy-MM-dd')+1 ");
		}
		if(ExStringUtils.isNotEmpty(objPage.getOrderBy()))//排序
			hql.append( " order by "+objPage.getOrderBy() +" "+ objPage.getOrder());
		return exGeneralHibernateDao.findByHql(objPage, hql.toString(), values);
	}
	
	//根据条件查找用户接受消息列表
	@Override
	@Transactional(readOnly=true)
	public Page findReceiveMessageByCondition(Map<String, Object> condition,Page objPage) throws ServiceException {
		Map<String,Object> values =  new HashMap<String, Object>();
		StringBuilder hql = new StringBuilder();
		
		hql.append( "select s from "+MessageReceiver.class.getSimpleName()+" r,"+MessageSender.class.getSimpleName()+" s where r.isDeleted = :isDeleted ");
		values.put("isDeleted", 0);
				
		if(condition.containsKey("msgTitle")){//标题
			hql.append(" and lower(r.message.msgTitle) like lower(:msgTitle) ");
			values.put("msgTitle", "%"+condition.get("msgTitle")+"%");
		}
		if(condition.containsKey("msgType")){//类型
			hql.append( " and r.message.msgType =:msgType ");
			values.put("msgType", condition.get("msgType"));
		}		
		if(condition.containsKey("startDate")){//开始时间
			hql.append(" and r.message.sendTime >= to_date('"+condition.get("startDate").toString()+"','yyyy-MM-dd') ");
		}
		if(condition.containsKey("endDate")){//结束时间
			hql.append( " and r.message.sendTime <= to_date('"+condition.get("endDate").toString()+"','yyyy-MM-dd')+1 ");
		}
		//发送时间小于当前
		hql.append( " and r.message.sendTime <=:today ");
		values.put("today", new Date());
		
		hql.append( " and ( 1=0 or r.receiveType = 'user' and r.userIds like '%"+(condition.containsKey("userId")?condition.get("userId"):"")+"%' ");
		hql.append( " or r.receiveType = 'org' and r.orgUnitCodes like '%"+(condition.containsKey("unitCode")?condition.get("unitCode"):"")+"%' ");
		hql.append( "or r.receiveType = 'role' and (1=0 ");
		if(condition.containsKey("unitCode")){
			String roles = null!=condition.get("roleCode")?condition.get("roleCode").toString():"";
			for (String r : roles.split(",")) 
				hql.append( " or r.roleCodes like '%"+r+"%' ");
		}		
		hql.append( " )");
		hql.append(" or r.receiveType like '%org%' and r.orgUnitCodes like '%"+(condition.containsKey("unitCode")?condition.get("unitCode"):"")+"%' ");
		hql.append( "and r.receiveType like '%role%' and (1=0 ");
		if(condition.containsKey("unitCode")){
			String roles = null!=condition.get("roleCode")?condition.get("roleCode").toString():"";
			for (String r : roles.split(",")) 
				hql.append( " or r.roleCodes like '%"+r+"%' ");
		}		
		hql.append( " ))");
		hql.append(" and s.message.resourceid=r.message.resourceid ");
		if(condition.containsKey("senderIds")){//发送人
			hql.append(" and s.senderId in ("+condition.get("senderIds")+") ");
		}
		if(ExStringUtils.isNotEmpty(objPage.getOrderBy()))//排序
			hql.append( " order by r."+objPage.getOrderBy() +" "+ objPage.getOrder());
		
		return exGeneralHibernateDao.findByHql(objPage, hql.toString(), values);
	}
	
	//获取用户消息列表，用于首页
	@Override
	@Transactional(readOnly=true)
	public List<Map<String, Object>> getUserMessageList(Map<String, Object> condition) throws ServiceException {
		//构造page对象
		Page objPage = new Page();
		objPage.setPageSize(15);
		if(condition.containsKey("fetchSize")){//获取的消息条数
			objPage.setPageSize(Integer.parseInt(condition.get("fetchSize").toString()));
		}
		
		objPage.setOrderBy("message.sendTime"); //按发送时间排序
		objPage.setOrder(Page.DESC);
				
		Page messagePage = findReceiveMessageByCondition(condition, objPage);
		
		//获取阅读人列表
		List<String> statlist = getIsReadMsgIds(condition.get("userId").toString());
		
		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();			
		for (Object o : messagePage.getResult()) {
			MessageSender sender = (MessageSender)o;
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("resourceid", sender.getMessage().getResourceid());
			map.put("msgType", JstlCustomFunction.dictionaryCode2Value("CodeMsgType", sender.getMessage().getMsgType()));
			map.put("msgTitle", sender.getMessage().getMsgTitle());
			try {
				map.put("sendTime", ExDateUtils.formatDateStr(sender.getMessage().getSendTime(), "MM/dd HH:mm"));
			} catch (ParseException e) {
				//noting
			}
			map.put("sender", sender.getSender());
			map.put("isRead", statlist.contains(sender.getMessage().getResourceid()));
			list.add(map);
		}
		
		return list;
	}

	@Override
	public void saveMessageStat(MessageStat messageStat) throws ServiceException {
		exGeneralHibernateDao.save(messageStat)	;	
	}

	@Override
	public MessageReceiver codesOrId2Name(MessageReceiver messageReceiver)	throws ServiceException {
		if(ExStringUtils.isNotEmpty(messageReceiver.getUserIds())){
			String[] userIds = messageReceiver.getUserIds().split(",");
			String userCnNames = "";
			for (String id : userIds){
				User user = userService.get(id);
				if(user != null){
					userCnNames += user.getCnName()+",";
				}				
			}
			messageReceiver.setUserCnNames(userCnNames);
		}
		if(ExStringUtils.isNotEmpty(messageReceiver.getOrgUnitCodes())){
			String[] orgUnitCodes = messageReceiver.getOrgUnitCodes().split(",");
			String orgUnitNames = "";
			for (String code : orgUnitCodes) 
				orgUnitNames += orgUnitService.findUniqueByProperty("unitCode", code).getUnitName()+",";
			if(ExStringUtils.isNotEmpty(orgUnitNames))
				orgUnitNames = orgUnitNames.substring(0, orgUnitNames.length()-1);
			messageReceiver.setOrgUnitNames(orgUnitNames);
		}
		if(ExStringUtils.isNotEmpty(messageReceiver.getRoleCodes())){
			String[] roleCodes = messageReceiver.getRoleCodes().split(",");
			String roleNames = "";
			for (String code : roleCodes) 
				roleNames += roleService.getRoleByRolecode(code).getRoleName()+",";
			if(ExStringUtils.isNotEmpty(roleNames))
				roleNames = roleNames.substring(0, roleNames.length()-1);
			messageReceiver.setRoleNames(roleNames);
		}
		return messageReceiver;
	}
	
		
}
